package cn.ug.pay.web.controller;

import cn.ug.aop.RequiresPermissions;
import cn.ug.bean.LoginBean;
import cn.ug.bean.base.*;
import cn.ug.bean.type.ResultType;
import cn.ug.config.Config;
import cn.ug.core.SerializeObjectError;
import cn.ug.core.login.LoginHelper;
import cn.ug.enums.RateKeyEnum;
import cn.ug.feign.MemberUserService;
import cn.ug.feign.RateSettingsService;
import cn.ug.member.bean.response.MemberUserBean;
import cn.ug.member.mq.MemberPasswordStatusMQ;
import cn.ug.mq.DelayMessagePostProcessor;
import cn.ug.msg.mq.Msg;
import cn.ug.pay.bean.WithdrawAuditBean;
import cn.ug.pay.bean.WithdrawBean;
import cn.ug.pay.bean.response.BankInfoBean;
import cn.ug.pay.bean.status.CommonConstants;
import cn.ug.pay.mapper.BankCardMapper;
import cn.ug.pay.mapper.BankInfoMapper;
import cn.ug.pay.mapper.entity.BankCard;
import cn.ug.pay.service.WithdrawService;
import cn.ug.service.SystemService;
import cn.ug.util.BigDecimalUtil;
import cn.ug.util.UF;
import cn.ug.web.controller.BaseController;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static cn.ug.bean.type.LogType.WITHDRAW_APPLY;
import static cn.ug.config.QueueName.QUEUE_MEMBER_PASSWORD_STATUS_DELAY;
import static cn.ug.config.QueueName.QUEUE_MSG_SEND;
import static org.springframework.web.bind.annotation.RequestMethod.*;

/**
 * 提现管理
 * @author kaiwotech
 */
@RestController
@RequestMapping("withdraw")
public class WithdrawController extends BaseController {

    @Resource
    private WithdrawService withdrawService;
    @Resource
    private MemberUserService memberUserService;
    @Resource
    private BankCardMapper bankCardMapper;
    @Resource
    private BankInfoMapper bankInfoMapper;
    @Resource
    private SystemService systemService;
    @Resource
    private Config config;
    @Resource
    private AmqpTemplate amqpTemplate;
    @Autowired
    private RateSettingsService rateSettingsService;
    private static Logger logger = LoggerFactory.getLogger(WithdrawController.class);
    /**
     * 根据ID查找信息
     * @param id		    ID
     * @return			    记录集
     */
    @RequestMapping(value = "{id}", method = GET)
    public SerializeObject find(@PathVariable String id) {
        if(StringUtils.isBlank(id)) {
            return new SerializeObjectError("00000002");
        }
        WithdrawAuditBean entity = withdrawService.findDetailById(id);
        if(null == entity || StringUtils.isBlank(entity.getId())) {
            return new SerializeObjectError("00000003");
        }
        return new SerializeObject<>(ResultType.NORMAL, entity);
    }

    /**
     * 发起申请
     * @param accessToken		登录成功后分配的Key
     * @param entity		    记录集
     * @param payPassword		交易密码
     * @return				    是否操作成功
     */
    @RequestMapping(method = POST)
    public SerializeObject update(@RequestHeader String accessToken, WithdrawBean entity, String payPassword) {
        if(null == entity || StringUtils.isBlank(payPassword) ||
                StringUtils.isBlank(entity.getBankCardId()) || BigDecimalUtil.isZeroOrNull(entity.getAmount())) {
            return new SerializeObjectError("00000002");
        }
        String memberId = LoginHelper.getLoginId();
        if(StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000102");
        }

        if (entity.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            return new SerializeObjectError("00000002");
        }

        // 验证银行是否维护中
        BankCard bankCard = bankCardMapper.findDefaultByMemberId(memberId);
        logger.info("银行卡维护状态：1");
        if (bankCard == null) {
            return new SerializeObjectError("17000411");
        }
        entity.setBankCardId(bankCard.getId());
        entity.setBankCode(bankCard.getBankCode());
        BankInfoBean bankInfoBean = bankInfoMapper.queryBankInfo(bankCard.getBankCode());
        if(bankInfoBean != null && CommonConstants.CardStatus.MAINTENANCE.getIndex() == bankInfoBean.getStatus()){
            Msg msg = new Msg();
            msg.setMemberId(memberId);
            msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.BANK_MAINTENANCE.getIndex());
            Map<String, String> paramMap = new HashMap<>();
            paramMap.put("bankName", cn.ug.util.StringUtils.sensitivityBankCard(bankCard.getCardNo()));
            msg.setParamMap(paramMap);
            amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
            return new SerializeObjectError("17000423");
        }

        // 交易密码验证
        SerializeObject obj = memberUserService.validatePayPassword(memberId, payPassword);
        if(null == obj || obj.getCode() != ResultType.NORMAL) {
            String log = "交易密码验证失败。 memberId = " + memberId;
            systemService.log(WITHDRAW_APPLY, log);
            SerializeObject paramBean  = rateSettingsService.get(RateKeyEnum.TRADE_PASSWORD.getKey());
            if (paramBean != null && paramBean.getData() != null) {
                JSONObject json = JSON.parseObject(JSONObject.toJSONString(paramBean.getData()));
                int isLimited = json.getIntValue("isLimited");
                int wrongTimes = json.getIntValue("wrongTimes");
                int minutes = json.getIntValue("minutes");
                if (isLimited == 1) {
                    SerializeObject<MemberUserBean> memberBean = memberUserService.findById(memberId);
                    if (null == memberBean || memberBean.getData() == null) {
                        return new SerializeObjectError("00000102");
                    }
                    MemberUserBean memberUserBean = memberBean.getData();
                    if (isLimited == 1 && memberUserBean.getTrdpassdStatus() == 1) {
                        SerializeObjectError result = new SerializeObjectError<>("17002034");
                        String msg = String.format(result.getMsg(), wrongTimes, minutes);
                        result.setMsg(msg);
                        return result;
                    }
                    int actualWrongTimes = memberUserBean.getTrdpassdWrongTimes();
                    actualWrongTimes++;
                    int status = 0;
                    if (wrongTimes <= actualWrongTimes) {
                        status = 1;
                    }
                    memberUserService.modifyWrongTimes(memberUserBean.getId(), 2, actualWrongTimes, status);
                    if (wrongTimes <= actualWrongTimes) {
                        MemberPasswordStatusMQ mq = new MemberPasswordStatusMQ();
                        mq.setMemberId(memberUserBean.getId());
                        mq.setType(2);
                        amqpTemplate.convertAndSend(QUEUE_MEMBER_PASSWORD_STATUS_DELAY, mq, new DelayMessagePostProcessor(minutes * 60 * 1000));

                        SerializeObjectError result = new SerializeObjectError<>("17002034");
                        String msg = String.format(result.getMsg(), wrongTimes, minutes);
                        result.setMsg(msg);
                        return result;
                    }
                }
            }
            info(log);
            return obj;
        }
        memberUserService.modifyWrongTimes(memberId, 2, 0, 0);
        entity.setMemberId(memberId);
        withdrawService.save(entity);
        return new SerializeObject(ResultType.NORMAL, "00000001");
    }

    /**
     * 一级审核
     * @param accessToken		登录成功后分配的Key
     * @param id			    ID数组
     * @param auditStatus	    审核意见（1：通过 2：拒绝）
     * @param description	    审核意见详情
     * @return				    是否操作成功
     */
    @RequiresPermissions("pay:withdraw:audit:1")
    @RequestMapping(value = "auditOne", method = PUT)
    public SerializeObject auditOne(@RequestHeader String accessToken, String[] id, Integer auditStatus, String description) {
        if(null == id || id.length <= 0) {
            return new SerializeObjectError("00000002");
        }
        if(null == auditStatus || auditStatus < 1 || auditStatus > 2) {
            return new SerializeObjectError("00000002");
        }
        LoginBean loginBean = LoginHelper.getLoginBean();
        if(null == loginBean) {
            return new SerializeObjectError("00000102");
        }
        String memberId = loginBean.getId();
        String memberName = loginBean.getName();

        int rows = withdrawService.audit(id, 1, auditStatus, description, memberId, memberName);
        return new SerializeObject(ResultType.NORMAL, "00000001");
    }

    /**
     * 二级审核
     * @param accessToken		登录成功后分配的Key
     * @param id			    ID数组
     * @param auditStatus	    审核意见（1：通过 2：拒绝）
     * @param description	    审核意见详情
     * @return				    是否操作成功
     */
    @RequiresPermissions("pay:withdraw:audit:2")
    @RequestMapping(value = "auditTwo", method = PUT)
    public SerializeObject auditTwo(@RequestHeader String accessToken, String[] id, Integer auditStatus, String description) {
        if(null == id || id.length <= 0) {
            return new SerializeObjectError("00000002");
        }
        if(null == auditStatus || auditStatus < 1 || auditStatus > 2) {
            return new SerializeObjectError("00000002");
        }
        LoginBean loginBean = LoginHelper.getLoginBean();
        if(null == loginBean) {
            return new SerializeObjectError("00000102");
        }
        String memberId = loginBean.getId();
        String memberName = loginBean.getName();

        int rows = withdrawService.audit(id, 2, auditStatus, description, memberId, memberName);
        return new SerializeObject(ResultType.NORMAL, "00000001");
    }

    /**
     * 根据当前登录用户查询数据
     * @param accessToken	    登录成功后分配的Key
     * @param order		        排序
     * @param page		        分页
     * @param addTimeMinString	最小操作时间(yyyy-MM-dd)
     * @param addTimeMaxString  最大操作时间(yyyy-MM-dd)
     * @return			        分页数据
     */
    @RequestMapping(value = "queryByMemberId", method = GET)
    public SerializeObject<DataTable<WithdrawAuditBean>> queryByMemberId(@RequestHeader String accessToken, Order order, Page page, String addTimeMinString, String addTimeMaxString) {
        if(page.getPageSize() <= 0) {
            page.setPageSize(config.getPageSize());
        }
        LocalDateTime addTimeMin = null;
        LocalDateTime addTimeMax = null;
        if(StringUtils.isNotBlank(addTimeMinString)) {
            addTimeMin = UF.getDate(addTimeMinString);
        }
        if(StringUtils.isNotBlank(addTimeMaxString)) {
            addTimeMax = UF.getDate(addTimeMaxString);
        }
        String memberId = LoginHelper.getLoginId();
        if(StringUtils.isBlank(memberId)) {
            return new SerializeObjectError<>("00000102");
        }

        DataTable<WithdrawAuditBean> dataTable = withdrawService.queryDetail(order.getOrder(), order.getSort(), page.getPageNum(), page.getPageSize(), null, null, null,
                null, null, addTimeMin, addTimeMax, null, null,
                memberId, null, null, null, null, null);
        return new SerializeObject<>(ResultType.NORMAL, dataTable);
    }

    /**
     * 审核页面查询数据
     * @param accessToken	        登录成功后分配的Key
     * @param order		            排序
     * @param page		            分页
     * @param type	                类型  1:一级提现待审 2:一级提现已审 3:二级提现待审 4:二级提现已审
     * @param status		        提现状态  0:全部 1:待提现 2:处理中 3:成功 4:失败
     * @param amountMin		        最小提现金额
     * @param amountMax		        最大提现金额
     * @param addTimeMinString	    最小操作时间
     * @param addTimeMaxString	    最大操作时间
     * @param modifyTimeMinString	最小反馈时间
     * @param modifyTimeMaxString   最大反馈时间
     * @param memberId		        会员ID
     * @param memberName	        会员名称
     * @param memberMobile	        会员手机
     * @param keyword		        关键字
     * @return			            分页数据
     */
    @RequestMapping(value = "auditQuery", method = GET)
    public SerializeObject<DataTable<WithdrawAuditBean>> auditQuery(@RequestHeader String accessToken, Order order, Page page, Integer type, Integer status,
                                                          BigDecimal amountMin, BigDecimal amountMax,
                                                          String addTimeMinString, String addTimeMaxString,
                                                          String modifyTimeMinString, String modifyTimeMaxString,
                                                          String memberId, String memberName, String memberMobile, String keyword, String channelId) {
        if(page.getPageSize() <= 0) {
            page.setPageSize(config.getPageSize());
        }
        if(null == status || status < 0) {
            status = 0;
        }
        if(null == type || type < 1) {
            type = 1;
        }
        LocalDateTime addTimeMin = null;
        LocalDateTime addTimeMax = null;
        LocalDateTime modifyTimeMin = null;
        LocalDateTime modifyTimeMax = null;
        if(StringUtils.isNotBlank(addTimeMinString)) {
            addTimeMin = UF.getDate(addTimeMinString);
        }
        if(StringUtils.isNotBlank(addTimeMaxString)) {
            addTimeMax = UF.getDate(addTimeMaxString);
        }
        if(StringUtils.isNotBlank(modifyTimeMinString)) {
            modifyTimeMin = UF.getDate(modifyTimeMinString);
        }
        if(StringUtils.isNotBlank(modifyTimeMaxString)) {
            modifyTimeMax = UF.getDate(modifyTimeMaxString);
        }
        keyword = UF.toString(keyword);

        // 审核状态  审核状态  1:未审核 2:一级审核成功 3一级审核失败 4:二级审核成功 5:二级审核失败
        List<Integer> auditStatusList = null;
        switch (type) {
            case 1: {
                // 一级提现待审
                auditStatusList = Arrays.asList(1);
                break;
            }
            case 2: {
                // 一级提现已审
                auditStatusList = Arrays.asList(2, 3, 4, 5);
                break;
            }
            case 3: {
                // 二级提现待审
                auditStatusList = Arrays.asList(2);
                break;
            }
            case 4: {
                // 二级提现已审
                auditStatusList = Arrays.asList(4, 5);
                break;
            }
            default:
        }

        DataOtherTable<WithdrawAuditBean> dataTable = withdrawService.queryDetail(order.getOrder(), order.getSort(), page.getPageNum(), page.getPageSize(), null, status, null,
                amountMin, amountMax, addTimeMin, addTimeMax, modifyTimeMin, modifyTimeMax,
                memberId, memberName, memberMobile, keyword, auditStatusList, channelId);
        return new SerializeObject<>(ResultType.NORMAL, dataTable);
    }

    /**
     * 查询数据
     * @param accessToken	        登录成功后分配的Key
     * @param order		            排序
     * @param page		            分页
     * @param status		        提现状态  0:全部 1:待提现 2:处理中 3:成功 4:失败
     * @param auditStatus	        审核状态  0:全部 审核状态  1:未审核 2:一级审核成功 3一级审核失败 4:二级审核成功 5:二级审核失败
     * @param amountMin		        最小提现金额
     * @param amountMax		        最大提现金额
     * @param addTimeMinString	    最小操作时间
     * @param addTimeMaxString	    最大操作时间
     * @param modifyTimeMinString	最小反馈时间
     * @param modifyTimeMaxString   最大反馈时间
     * @param memberId		        会员ID
     * @param memberName	        会员名称
     * @param memberMobile	        会员手机
     * @param keyword		        关键字
     * @return			            分页数据
     */
    @RequestMapping(method = GET)
    public SerializeObject<DataTable<WithdrawAuditBean>> query(@RequestHeader String accessToken, Order order, Page page, Integer status, Integer auditStatus,
                                                               BigDecimal amountMin, BigDecimal amountMax,
                                                               String addTimeMinString, String addTimeMaxString,
                                                               String modifyTimeMinString, String modifyTimeMaxString,
                                                               String memberId, String memberName, String memberMobile, String keyword) {
        if(page.getPageSize() <= 0) {
            page.setPageSize(config.getPageSize());
        }
        if(null == status || status < 0) {
            status = 0;
        }
        if(null == auditStatus || auditStatus < 0) {
            auditStatus = 0;
        }
        LocalDateTime addTimeMin = null;
        LocalDateTime addTimeMax = null;
        LocalDateTime modifyTimeMin = null;
        LocalDateTime modifyTimeMax = null;
        if(StringUtils.isNotBlank(addTimeMinString)) {
            addTimeMin = UF.getDate(addTimeMinString);
        }
        if(StringUtils.isNotBlank(addTimeMaxString)) {
            addTimeMax = UF.getDate(addTimeMaxString);
        }
        if(StringUtils.isNotBlank(modifyTimeMinString)) {
            modifyTimeMin = UF.getDate(modifyTimeMinString);
        }
        if(StringUtils.isNotBlank(modifyTimeMaxString)) {
            modifyTimeMax = UF.getDate(modifyTimeMaxString);
        }
        keyword = UF.toString(keyword);

        DataTable<WithdrawAuditBean> dataTable = withdrawService.queryDetail(order.getOrder(), order.getSort(), page.getPageNum(), page.getPageSize(), null, status, auditStatus,
                amountMin, amountMax, addTimeMin, addTimeMax, modifyTimeMin, modifyTimeMax,
                memberId, memberName, memberMobile, keyword, null, null);
        return new SerializeObject<>(ResultType.NORMAL, dataTable);
    }


    /**
     * 查询当前用户的提现等费用信息
     * @param accessToken
     * @param amount
     * @return
     */
    @RequestMapping(value = "queryWithdrawInfo", method = GET)
    public SerializeObject queryWithdrawInfo(@RequestHeader String accessToken,BigDecimal amount) {
        LoginBean loginBean = LoginHelper.getLoginBean();
        if(null == loginBean) {
            return new SerializeObjectError("00000102");
        }
        String memberId = loginBean.getId();
        return new SerializeObject<>(ResultType.NORMAL, withdrawService.queryWithdrawInfo(memberId,amount));
    }
}
